package org.zhb.sql.query.core.config;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;

import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import org.zhb.sql.query.core.realm.MonitorRealm;

import net.sf.ehcache.CacheManager;

@Configuration
public class ShiroConfig {
	Logger logger = LoggerFactory.getLogger(ShiroConfig.class);
	@Autowired
	private CacheManager cacheManager;

	@Bean
	public EhCacheManager getEhCacheManager() {
		EhCacheManager em = new EhCacheManager();
		em.setCacheManager(cacheManager);
		return em;
	}

	@Bean(name = "monitorRealm")
	public MonitorRealm monitorRealm(EhCacheManager cacheManager) {
		MonitorRealm monitorRealm = new MonitorRealm();
		monitorRealm.setCacheManager(cacheManager);
		return new MonitorRealm();
	}

	/*
	 * @Bean public FilterRegistrationBean filterRegistrationBean() {
	 * FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
	 * filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter"));
	 * filterRegistration.setOrder(1); //
	 * 该值缺省为false,表示生命周期由SpringApplicationContext管理,
	 * 设置为true则表示由ServletContainer管理
	 * filterRegistration.addInitParameter("targetFilterLifecycle", "true");
	 * filterRegistration.setEnabled(true);
	 * filterRegistration.addUrlPatterns("/*"); return filterRegistration; }
	 */

	@Bean(name = "lifecycleBeanPostProcessor")
	public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
		return new LifecycleBeanPostProcessor();
	}

	@DependsOn("lifecycleBeanPostProcessor")
	public @Bean DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
		DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
		defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
		return defaultAdvisorAutoProxyCreator;
	}

	@Bean(name = "securityManager")
	public DefaultWebSecurityManager securityManager(MonitorRealm monitorRealm, EhCacheManager cacheManager) {
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		securityManager.setRealm(monitorRealm);
		// 用户授权/认证信息Cache, 采用EhCache 缓存
		securityManager.setCacheManager(cacheManager);
		return securityManager;
	}

	public @Bean AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
			DefaultWebSecurityManager securityManager) {
		AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
		authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
		return authorizationAttributeSourceAdvisor;
	}

	/**
	 * 加载shiroFilter权限控制规则（从数据库读取然后配置）
	 * 
	 * @author zhb
	 */
	private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean) {
		// 下面这些规则配置最好配置到配置文件中
		Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
		// authc：该过滤器下的页面必须验证后才能访问，它是Shiro内置的一个拦截器org.apache.shiro.web.filter.authc.FormAuthenticationFilter
		filterChainDefinitionMap.put("/resources/**", "anon");
		filterChainDefinitionMap.put("/modulejs/**", "anon");
		filterChainDefinitionMap.put("/common/**", "anon");
		filterChainDefinitionMap.put("/index*", "anon");
		filterChainDefinitionMap.put("/error*", "anon");
		filterChainDefinitionMap.put("/register*", "anon");
		filterChainDefinitionMap.put("/login*", "anon");
		filterChainDefinitionMap.put("/**", "authc");
		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
	}

	/**
	 * ShiroFilter<br/>
	 * 注意这里参数中的 StudentService 和 IScoreDao 只是一个例子，因为我们在这里可以用这样的方式获取到相关访问数据库的对象，
	 * 然后读取数据库相关配置，配置到 shiroFilterFactoryBean 的访问规则中。实际项目中，请使用自己的Service来处理业务逻辑。
	 */
	@Bean(name = "shiroFilter")
	public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		// 必须设置 SecurityManager
		shiroFilterFactoryBean.setSecurityManager(securityManager);
		shiroFilterFactoryBean.setLoginUrl("/index");
		// 登录成功后要跳转的连接
		shiroFilterFactoryBean.setSuccessUrl("/main");
		shiroFilterFactoryBean.setUnauthorizedUrl("/error");
		loadShiroFilterChain(shiroFilterFactoryBean);
		return shiroFilterFactoryBean;
	}

	/**
	 * 异常处理
	 * 
	 * @return
	 */
	public @Bean SimpleMappingExceptionResolver simpleMappingExceptionResolver() {
		SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver();
		Properties properties = new Properties();
		properties.setProperty("org.apache.shiro.authz.UnauthorizedException", "/error");
		exceptionResolver.setExceptionMappings(properties);
		return exceptionResolver;
	}

	public @Bean MethodInvokingFactoryBean methodInvokingFactoryBean(DefaultWebSecurityManager securityManager) {
		MethodInvokingFactoryBean invokingFactoryBean = new MethodInvokingFactoryBean();
		invokingFactoryBean.setStaticMethod("org.apache.shiro.SecurityUtils.setSecurityManager");
		Object[] objects = new Object[] { securityManager };
		invokingFactoryBean.setArguments(objects);
		return invokingFactoryBean;
	}

}
